


<!DOCTYPE html>
<html id="htmlId">
<head>
  <title>Coverage Report > MapParser</title>
  <style type="text/css">
    @import "../../css/coverage.css";
    @import "../../css/highlight-idea.css";
  </style>
  <script type="text/javascript" src="../../js/highlight.pack.js"></script>
</head>

<body>
<div class="content">
<div class="breadCrumbs">
Current scope:     <a href="../../index.html">all classes</a>
    <span class="separator">|</span>
    <a href="../index.html">nl.tudelft.jpacman.level</a>
</div>

<h1>Coverage Summary for Class: MapParser (nl.tudelft.jpacman.level)</h1>

<table class="coverageStats">
<tr>
  <th class="name">Class</th>
<th class="coverageStat 
">
  Class, %
</th>
<th class="coverageStat 
">
  Method, %
</th>
<th class="coverageStat 
">
  Line, %
</th>
</tr>
<tr>
  <td class="name">MapParser</td>
<td class="coverageStat">
  <span class="percent">
    100%
  </span>
  <span class="absValue">
    (1/1)
  </span>
</td>
<td class="coverageStat">
  <span class="percent">
    90%
  </span>
  <span class="absValue">
    (9/10)
  </span>
</td>
<td class="coverageStat">
  <span class="percent">
    91.5%
  </span>
  <span class="absValue">
    (65/71)
  </span>
</td>
</tr>

</table>

<br/>
<br/>


<pre>
<div class="sourceCode" id="sourceCode"><i class="no-highlight">1</i>&nbsp;package nl.tudelft.jpacman.level;
<i class="no-highlight">2</i>&nbsp;
<i class="no-highlight">3</i>&nbsp;import java.io.BufferedReader;
<i class="no-highlight">4</i>&nbsp;import java.io.IOException;
<i class="no-highlight">5</i>&nbsp;import java.io.InputStream;
<i class="no-highlight">6</i>&nbsp;import java.io.InputStreamReader;
<i class="no-highlight">7</i>&nbsp;import java.util.ArrayList;
<i class="no-highlight">8</i>&nbsp;import java.util.List;
<i class="no-highlight">9</i>&nbsp;
<i class="no-highlight">10</i>&nbsp;import nl.tudelft.jpacman.PacmanConfigurationException;
<i class="no-highlight">11</i>&nbsp;import nl.tudelft.jpacman.board.Board;
<i class="no-highlight">12</i>&nbsp;import nl.tudelft.jpacman.board.BoardFactory;
<i class="no-highlight">13</i>&nbsp;import nl.tudelft.jpacman.board.Square;
<i class="no-highlight">14</i>&nbsp;import nl.tudelft.jpacman.npc.Ghost;
<i class="no-highlight">15</i>&nbsp;import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
<i class="no-highlight">16</i>&nbsp;
<i class="no-highlight">17</i>&nbsp;/**
<i class="no-highlight">18</i>&nbsp; * Creates new {@link Level}s from text representations.
<i class="no-highlight">19</i>&nbsp; *
<i class="no-highlight">20</i>&nbsp; * @author Jeroen Roosen
<i class="no-highlight">21</i>&nbsp; */
<i class="no-highlight">22</i>&nbsp;public class MapParser {
<i class="no-highlight">23</i>&nbsp;
<i class="no-highlight">24</i>&nbsp;    /**
<i class="no-highlight">25</i>&nbsp;     * The factory that creates the levels.
<i class="no-highlight">26</i>&nbsp;     */
<i class="no-highlight">27</i>&nbsp;    private final LevelFactory levelCreator;
<i class="no-highlight">28</i>&nbsp;
<i class="no-highlight">29</i>&nbsp;    /**
<i class="no-highlight">30</i>&nbsp;     * The factory that creates the squares and board.
<i class="no-highlight">31</i>&nbsp;     */
<i class="no-highlight">32</i>&nbsp;    private final BoardFactory boardCreator;
<i class="no-highlight">33</i>&nbsp;
<i class="no-highlight">34</i>&nbsp;    /**
<i class="no-highlight">35</i>&nbsp;     * Creates a new map parser.
<i class="no-highlight">36</i>&nbsp;     *
<i class="no-highlight">37</i>&nbsp;     * @param levelFactory
<i class="no-highlight">38</i>&nbsp;     *            The factory providing the NPC objects and the level.
<i class="no-highlight">39</i>&nbsp;     * @param boardFactory
<i class="no-highlight">40</i>&nbsp;     *            The factory providing the Square objects and the board.
<i class="no-highlight">41</i>&nbsp;     */
<b class="fc"><i class="no-highlight">42</i>&nbsp;    public MapParser(LevelFactory levelFactory, BoardFactory boardFactory) {</b>
<b class="fc"><i class="no-highlight">43</i>&nbsp;        this.levelCreator = levelFactory;</b>
<b class="fc"><i class="no-highlight">44</i>&nbsp;        this.boardCreator = boardFactory;</b>
<b class="fc"><i class="no-highlight">45</i>&nbsp;    }</b>
<i class="no-highlight">46</i>&nbsp;
<i class="no-highlight">47</i>&nbsp;    /**
<i class="no-highlight">48</i>&nbsp;     * Parses the text representation of the board into an actual level.
<i class="no-highlight">49</i>&nbsp;     *
<i class="no-highlight">50</i>&nbsp;     * &lt;ul&gt;
<i class="no-highlight">51</i>&nbsp;     * &lt;li&gt;Supported characters:
<i class="no-highlight">52</i>&nbsp;     * &lt;li&gt;&#39; &#39; (space) an empty square.
<i class="no-highlight">53</i>&nbsp;     * &lt;li&gt;&#39;#&#39; (bracket) a wall.
<i class="no-highlight">54</i>&nbsp;     * &lt;li&gt;&#39;.&#39; (period) a square with a pellet.
<i class="no-highlight">55</i>&nbsp;     * &lt;li&gt;&#39;P&#39; (capital P) a starting square for players.
<i class="no-highlight">56</i>&nbsp;     * &lt;li&gt;&#39;G&#39; (capital G) a square with a ghost.
<i class="no-highlight">57</i>&nbsp;     * &lt;/ul&gt;
<i class="no-highlight">58</i>&nbsp;     *
<i class="no-highlight">59</i>&nbsp;     * @param map
<i class="no-highlight">60</i>&nbsp;     *            The text representation of the board, with map[x][y]
<i class="no-highlight">61</i>&nbsp;     *            representing the square at position x,y.
<i class="no-highlight">62</i>&nbsp;     * @return The level as represented by this text.
<i class="no-highlight">63</i>&nbsp;     */
<i class="no-highlight">64</i>&nbsp;    public Level parseMap(char[][] map) {
<b class="fc"><i class="no-highlight">65</i>&nbsp;        int width = map.length;</b>
<b class="fc"><i class="no-highlight">66</i>&nbsp;        int height = map[0].length;</b>
<i class="no-highlight">67</i>&nbsp;
<b class="fc"><i class="no-highlight">68</i>&nbsp;        Square[][] grid = new Square[width][height];</b>
<i class="no-highlight">69</i>&nbsp;
<b class="fc"><i class="no-highlight">70</i>&nbsp;        List&lt;Ghost&gt; ghosts = new ArrayList&lt;&gt;();</b>
<b class="fc"><i class="no-highlight">71</i>&nbsp;        List&lt;Square&gt; startPositions = new ArrayList&lt;&gt;();</b>
<i class="no-highlight">72</i>&nbsp;
<b class="fc"><i class="no-highlight">73</i>&nbsp;        makeGrid(map, width, height, grid, ghosts, startPositions);</b>
<i class="no-highlight">74</i>&nbsp;
<b class="fc"><i class="no-highlight">75</i>&nbsp;        Board board = boardCreator.createBoard(grid);</b>
<b class="fc"><i class="no-highlight">76</i>&nbsp;        return levelCreator.createLevel(board, ghosts, startPositions);</b>
<i class="no-highlight">77</i>&nbsp;    }
<i class="no-highlight">78</i>&nbsp;
<i class="no-highlight">79</i>&nbsp;    private void makeGrid(char[][] map, int width, int height,
<i class="no-highlight">80</i>&nbsp;                          Square[][] grid, List&lt;Ghost&gt; ghosts, List&lt;Square&gt; startPositions) {
<b class="fc"><i class="no-highlight">81</i>&nbsp;        for (int x = 0; x &lt; width; x++) {</b>
<b class="fc"><i class="no-highlight">82</i>&nbsp;            for (int y = 0; y &lt; height; y++) {</b>
<b class="fc"><i class="no-highlight">83</i>&nbsp;                char c = map[x][y];</b>
<b class="fc"><i class="no-highlight">84</i>&nbsp;                addSquare(grid, ghosts, startPositions, x, y, c);</b>
<i class="no-highlight">85</i>&nbsp;            }
<i class="no-highlight">86</i>&nbsp;        }
<b class="fc"><i class="no-highlight">87</i>&nbsp;    }</b>
<i class="no-highlight">88</i>&nbsp;
<i class="no-highlight">89</i>&nbsp;    /**
<i class="no-highlight">90</i>&nbsp;     * Adds a square to the grid based on a given character. These
<i class="no-highlight">91</i>&nbsp;     * character come from the map files and describe the type
<i class="no-highlight">92</i>&nbsp;     * of square.
<i class="no-highlight">93</i>&nbsp;     *
<i class="no-highlight">94</i>&nbsp;     * @param grid
<i class="no-highlight">95</i>&nbsp;     *            The grid of squares with board[x][y] being the
<i class="no-highlight">96</i>&nbsp;     *            square at column x, row y.
<i class="no-highlight">97</i>&nbsp;     * @param ghosts
<i class="no-highlight">98</i>&nbsp;     *            List of all ghosts that were added to the map.
<i class="no-highlight">99</i>&nbsp;     * @param startPositions
<i class="no-highlight">100</i>&nbsp;     *            List of all start positions that were added
<i class="no-highlight">101</i>&nbsp;     *            to the map.
<i class="no-highlight">102</i>&nbsp;     * @param x
<i class="no-highlight">103</i>&nbsp;     *            x coordinate of the square.
<i class="no-highlight">104</i>&nbsp;     * @param y
<i class="no-highlight">105</i>&nbsp;     *            y coordinate of the square.
<i class="no-highlight">106</i>&nbsp;     * @param c
<i class="no-highlight">107</i>&nbsp;     *            Character describing the square type.
<i class="no-highlight">108</i>&nbsp;     */
<i class="no-highlight">109</i>&nbsp;    protected void addSquare(Square[][] grid, List&lt;Ghost&gt; ghosts,
<i class="no-highlight">110</i>&nbsp;                             List&lt;Square&gt; startPositions, int x, int y, char c) {
<b class="fc"><i class="no-highlight">111</i>&nbsp;        switch (c) {</b>
<i class="no-highlight">112</i>&nbsp;            case &#39; &#39;:
<b class="fc"><i class="no-highlight">113</i>&nbsp;                grid[x][y] = boardCreator.createGround();</b>
<b class="fc"><i class="no-highlight">114</i>&nbsp;                break;</b>
<i class="no-highlight">115</i>&nbsp;            case &#39;#&#39;:
<b class="fc"><i class="no-highlight">116</i>&nbsp;                grid[x][y] = boardCreator.createWall();</b>
<b class="fc"><i class="no-highlight">117</i>&nbsp;                break;</b>
<i class="no-highlight">118</i>&nbsp;            case &#39;.&#39;:
<b class="fc"><i class="no-highlight">119</i>&nbsp;                Square pelletSquare = boardCreator.createGround();</b>
<b class="fc"><i class="no-highlight">120</i>&nbsp;                grid[x][y] = pelletSquare;</b>
<b class="fc"><i class="no-highlight">121</i>&nbsp;                levelCreator.createPellet().occupy(pelletSquare);</b>
<b class="fc"><i class="no-highlight">122</i>&nbsp;                break;</b>
<i class="no-highlight">123</i>&nbsp;            case &#39;G&#39;:
<b class="fc"><i class="no-highlight">124</i>&nbsp;                Square ghostSquare = makeGhostSquare(ghosts, levelCreator.createGhost());</b>
<b class="fc"><i class="no-highlight">125</i>&nbsp;                grid[x][y] = ghostSquare;</b>
<b class="fc"><i class="no-highlight">126</i>&nbsp;                break;</b>
<i class="no-highlight">127</i>&nbsp;            case &#39;P&#39;:
<b class="fc"><i class="no-highlight">128</i>&nbsp;                Square playerSquare = boardCreator.createGround();</b>
<b class="fc"><i class="no-highlight">129</i>&nbsp;                grid[x][y] = playerSquare;</b>
<b class="fc"><i class="no-highlight">130</i>&nbsp;                startPositions.add(playerSquare);</b>
<b class="fc"><i class="no-highlight">131</i>&nbsp;                break;</b>
<i class="no-highlight">132</i>&nbsp;            default:
<b class="nc"><i class="no-highlight">133</i>&nbsp;                throw new PacmanConfigurationException(&quot;Invalid character at &quot;</b>
<i class="no-highlight">134</i>&nbsp;                    + x + &quot;,&quot; + y + &quot;: &quot; + c);
<i class="no-highlight">135</i>&nbsp;        }
<b class="fc"><i class="no-highlight">136</i>&nbsp;    }</b>
<i class="no-highlight">137</i>&nbsp;
<i class="no-highlight">138</i>&nbsp;    /**
<i class="no-highlight">139</i>&nbsp;     * creates a Square with the specified ghost on it
<i class="no-highlight">140</i>&nbsp;     * and appends the placed ghost into the ghost list.
<i class="no-highlight">141</i>&nbsp;     *
<i class="no-highlight">142</i>&nbsp;     * @param ghosts all the ghosts in the level so far, the new ghost will be appended
<i class="no-highlight">143</i>&nbsp;     * @param ghost the newly created ghost to be placed
<i class="no-highlight">144</i>&nbsp;     * @return a square with the ghost on it.
<i class="no-highlight">145</i>&nbsp;     */
<i class="no-highlight">146</i>&nbsp;    protected Square makeGhostSquare(List&lt;Ghost&gt; ghosts, Ghost ghost) {
<b class="fc"><i class="no-highlight">147</i>&nbsp;        Square ghostSquare = boardCreator.createGround();</b>
<b class="fc"><i class="no-highlight">148</i>&nbsp;        ghosts.add(ghost);</b>
<b class="fc"><i class="no-highlight">149</i>&nbsp;        ghost.occupy(ghostSquare);</b>
<b class="fc"><i class="no-highlight">150</i>&nbsp;        return ghostSquare;</b>
<i class="no-highlight">151</i>&nbsp;    }
<i class="no-highlight">152</i>&nbsp;
<i class="no-highlight">153</i>&nbsp;    /**
<i class="no-highlight">154</i>&nbsp;     * Parses the list of strings into a 2-dimensional character array and
<i class="no-highlight">155</i>&nbsp;     * passes it on to {@link #parseMap(char[][])}.
<i class="no-highlight">156</i>&nbsp;     *
<i class="no-highlight">157</i>&nbsp;     * @param text
<i class="no-highlight">158</i>&nbsp;     *            The plain text, with every entry in the list being a equally
<i class="no-highlight">159</i>&nbsp;     *            sized row of squares on the board and the first element being
<i class="no-highlight">160</i>&nbsp;     *            the top row.
<i class="no-highlight">161</i>&nbsp;     * @return The level as represented by the text.
<i class="no-highlight">162</i>&nbsp;     * @throws PacmanConfigurationException If text lines are not properly formatted.
<i class="no-highlight">163</i>&nbsp;     */
<i class="no-highlight">164</i>&nbsp;    public Level parseMap(List&lt;String&gt; text) {
<i class="no-highlight">165</i>&nbsp;
<b class="fc"><i class="no-highlight">166</i>&nbsp;        checkMapFormat(text);</b>
<i class="no-highlight">167</i>&nbsp;
<b class="fc"><i class="no-highlight">168</i>&nbsp;        int height = text.size();</b>
<b class="fc"><i class="no-highlight">169</i>&nbsp;        int width = text.get(0).length();</b>
<i class="no-highlight">170</i>&nbsp;
<b class="fc"><i class="no-highlight">171</i>&nbsp;        char[][] map = new char[width][height];</b>
<b class="fc"><i class="no-highlight">172</i>&nbsp;        for (int x = 0; x &lt; width; x++) {</b>
<b class="fc"><i class="no-highlight">173</i>&nbsp;            for (int y = 0; y &lt; height; y++) {</b>
<b class="fc"><i class="no-highlight">174</i>&nbsp;                map[x][y] = text.get(y).charAt(x);</b>
<i class="no-highlight">175</i>&nbsp;            }
<i class="no-highlight">176</i>&nbsp;        }
<b class="fc"><i class="no-highlight">177</i>&nbsp;        return parseMap(map);</b>
<i class="no-highlight">178</i>&nbsp;    }
<i class="no-highlight">179</i>&nbsp;
<i class="no-highlight">180</i>&nbsp;    /**
<i class="no-highlight">181</i>&nbsp;     * Check the correctness of the map lines in the text.
<i class="no-highlight">182</i>&nbsp;     * @param text Map to be checked
<i class="no-highlight">183</i>&nbsp;     * @throws PacmanConfigurationException if map is not OK.
<i class="no-highlight">184</i>&nbsp;     */
<i class="no-highlight">185</i>&nbsp;    private void checkMapFormat(List&lt;String&gt; text) {
<b class="fc"><i class="no-highlight">186</i>&nbsp;        if (text == null) {</b>
<b class="nc"><i class="no-highlight">187</i>&nbsp;            throw new PacmanConfigurationException(</b>
<i class="no-highlight">188</i>&nbsp;                &quot;Input text cannot be null.&quot;);
<i class="no-highlight">189</i>&nbsp;        }
<i class="no-highlight">190</i>&nbsp;
<b class="fc"><i class="no-highlight">191</i>&nbsp;        if (text.isEmpty()) {</b>
<b class="nc"><i class="no-highlight">192</i>&nbsp;            throw new PacmanConfigurationException(</b>
<i class="no-highlight">193</i>&nbsp;                &quot;Input text must consist of at least 1 row.&quot;);
<i class="no-highlight">194</i>&nbsp;        }
<i class="no-highlight">195</i>&nbsp;
<b class="fc"><i class="no-highlight">196</i>&nbsp;        int width = text.get(0).length();</b>
<i class="no-highlight">197</i>&nbsp;
<b class="fc"><i class="no-highlight">198</i>&nbsp;        if (width == 0) {</b>
<b class="nc"><i class="no-highlight">199</i>&nbsp;            throw new PacmanConfigurationException(</b>
<i class="no-highlight">200</i>&nbsp;                &quot;Input text lines cannot be empty.&quot;);
<i class="no-highlight">201</i>&nbsp;        }
<i class="no-highlight">202</i>&nbsp;
<b class="fc"><i class="no-highlight">203</i>&nbsp;        for (String line : text) {</b>
<b class="fc"><i class="no-highlight">204</i>&nbsp;            if (line.length() != width) {</b>
<b class="nc"><i class="no-highlight">205</i>&nbsp;                throw new PacmanConfigurationException(</b>
<i class="no-highlight">206</i>&nbsp;                    &quot;Input text lines are not of equal width.&quot;);
<i class="no-highlight">207</i>&nbsp;            }
<b class="fc"><i class="no-highlight">208</i>&nbsp;        }</b>
<b class="fc"><i class="no-highlight">209</i>&nbsp;    }</b>
<i class="no-highlight">210</i>&nbsp;
<i class="no-highlight">211</i>&nbsp;    /**
<i class="no-highlight">212</i>&nbsp;     * Parses the provided input stream as a character stream and passes it
<i class="no-highlight">213</i>&nbsp;     * result to {@link #parseMap(List)}.
<i class="no-highlight">214</i>&nbsp;     *
<i class="no-highlight">215</i>&nbsp;     * @param source
<i class="no-highlight">216</i>&nbsp;     *            The input stream that will be read.
<i class="no-highlight">217</i>&nbsp;     * @return The parsed level as represented by the text on the input stream.
<i class="no-highlight">218</i>&nbsp;     * @throws IOException
<i class="no-highlight">219</i>&nbsp;     *             when the source could not be read.
<i class="no-highlight">220</i>&nbsp;     */
<i class="no-highlight">221</i>&nbsp;    public Level parseMap(InputStream source) throws IOException {
<b class="fc"><i class="no-highlight">222</i>&nbsp;        try (BufferedReader reader = new BufferedReader(new InputStreamReader(</b>
<i class="no-highlight">223</i>&nbsp;            source, &quot;UTF-8&quot;))) {
<b class="fc"><i class="no-highlight">224</i>&nbsp;            List&lt;String&gt; lines = new ArrayList&lt;&gt;();</b>
<b class="fc"><i class="no-highlight">225</i>&nbsp;            while (reader.ready()) {</b>
<b class="fc"><i class="no-highlight">226</i>&nbsp;                lines.add(reader.readLine());</b>
<i class="no-highlight">227</i>&nbsp;            }
<b class="fc"><i class="no-highlight">228</i>&nbsp;            return parseMap(lines);</b>
<b class="fc"><i class="no-highlight">229</i>&nbsp;        }</b>
<i class="no-highlight">230</i>&nbsp;    }
<i class="no-highlight">231</i>&nbsp;
<i class="no-highlight">232</i>&nbsp;    /**
<i class="no-highlight">233</i>&nbsp;     * Parses the provided input stream as a character stream and passes it
<i class="no-highlight">234</i>&nbsp;     * result to {@link #parseMap(List)}.
<i class="no-highlight">235</i>&nbsp;     *
<i class="no-highlight">236</i>&nbsp;     * @param mapName
<i class="no-highlight">237</i>&nbsp;     *            Name of a resource that will be read.
<i class="no-highlight">238</i>&nbsp;     * @return The parsed level as represented by the text on the input stream.
<i class="no-highlight">239</i>&nbsp;     * @throws IOException
<i class="no-highlight">240</i>&nbsp;     *             when the resource could not be read.
<i class="no-highlight">241</i>&nbsp;     */
<i class="no-highlight">242</i>&nbsp;    @SuppressFBWarnings(
<i class="no-highlight">243</i>&nbsp;        value = {&quot;OBL_UNSATISFIED_OBLIGATION&quot;, &quot;RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE&quot;},
<i class="no-highlight">244</i>&nbsp;        justification = &quot;try with resources always cleans up / false positive in java 11&quot;
<i class="no-highlight">245</i>&nbsp;    )
<i class="no-highlight">246</i>&nbsp;    public Level parseMap(String mapName) throws IOException {
<b class="fc"><i class="no-highlight">247</i>&nbsp;        try (InputStream boardStream = MapParser.class.getResourceAsStream(mapName)) {</b>
<b class="fc"><i class="no-highlight">248</i>&nbsp;            if (boardStream == null) {</b>
<b class="fc"><i class="no-highlight">249</i>&nbsp;                throw new PacmanConfigurationException(&quot;Could not get resource for: &quot; + mapName);</b>
<i class="no-highlight">250</i>&nbsp;            }
<b class="fc"><i class="no-highlight">251</i>&nbsp;            return parseMap(boardStream);</b>
<b class="fc"><i class="no-highlight">252</i>&nbsp;        }</b>
<i class="no-highlight">253</i>&nbsp;    }
<i class="no-highlight">254</i>&nbsp;
<i class="no-highlight">255</i>&nbsp;    /**
<i class="no-highlight">256</i>&nbsp;     * @return the BoardCreator
<i class="no-highlight">257</i>&nbsp;     */
<i class="no-highlight">258</i>&nbsp;    protected BoardFactory getBoardCreator() {
<b class="nc"><i class="no-highlight">259</i>&nbsp;        return boardCreator;</b>
<i class="no-highlight">260</i>&nbsp;    }
<i class="no-highlight">261</i>&nbsp;}
</div>
</pre>
</div>

<script type="text/javascript">
(function() {
    var msie = false, msie9 = false;
    /*@cc_on
      msie = true;
      @if (@_jscript_version >= 9)
        msie9 = true;
      @end
    @*/

    if (!msie || msie && msie9) {
        var codeBlock = document.getElementById('sourceCode');

        if (codeBlock) {
            hljs.highlightBlock(codeBlock);
        }
    }
})();
</script>

<div class="footer">
    
    <div style="float:right;">generated on 2022-05-22 18:55</div>
</div>
</body>
</html>
